#undef  xuser
#define xuser mixc::macro_private_log::inc
#include"concurrency/lock/mutex.hpp"
#include"configure/switch.hpp"
#include"macro/private/log.hpp"
#include"macro/xdebug_fail.hpp"
#include"macro/xdefer.hpp"
#include"interface/seqptr.hpp"
#include"io/tty.hpp"
#include"lang/cxx/index_of_last.hpp"
#include"lang/cxx/logger_helper.hpp"
#include"lang/cxx.hpp"
#include"utils/memory.hpp"
#include"utils/static_length_of.hpp"

namespace mixc::macro_private_log::origin{
    inline inc::mutex g_print_mutex;

    void log_set_color(message_type_t type){
        using namespace inc;
        tty_color_t conf[4];
        conf[uxx(success)] = tty_color_t::green;
        conf[uxx(normal )] = tty_color_t::light_gray;
        conf[uxx(warning)] = tty_color_t::yellow;
        conf[uxx(fail   )] = tty_color_t::red;
        tty->forecolor = conf[uxx(type)];
    }

    void log_header_lock_free(log_type_t log_type, asciis file, uxx line, asciis func_name){
        using namespace inc;
        uxx skip = 0;

        // skip 值可能不是固定的
        #if xuse_xdebug_short_path
            if (auto i = c08{file}.index_of_last(xmixc); i != not_exist){
                skip  = i + sizeof(xmixc);
                skip += file[skip] == '/' or file[skip] == '\\';
            }
        #endif

        struct classify{
            asciis      type;
            tty_color_t color;
        };

        classify conf[4];
        conf[uxx(for_debug)] = { "D ", tty_color_t::light_gray};
        conf[uxx(for_fail )] = { "E ", tty_color_t::red};
        conf[uxx(for_test )] = { "T ", tty_color_t::blue};
        conf[uxx(for_hint )] = { "I ", tty_color_t::gray};

        auto i = uxx(log_type);
        file += skip;
        tty->forecolor = conf[i].color;
        tty.write(conf[i].type, vl{file, ':', line}.l(40), " | ", v{func_name}.l(24), " | ");
    }

    void log(
        log_type_t          log_type, 
        asciis              file, 
        uxx                 line, 
        asciis              func_name, 
        asciis              message, 
        message_type_t      message_type
    ){
        using namespace inc;

        g_print_mutex.lock_non_load_store([&](){
            tty_color_t color = tty->forecolor;
            log_header_lock_free(log_type, file, line, func_name);
            log_set_color(message_type);
            tty.write_line(message);
            tty->forecolor = color;
        });
    }

    void log(
        log_type_t          log_type, 
        asciis              file, 
        uxx                 line, 
        asciis              func_name, 
        asciis              message, 
        message_type_t      message_type,
        mix_item          * items, 
        uxx                 items_length
    ){
        using namespace inc;

        char buffer[256];
        auto need_free      = false;

        // 注意：
        // 如果 inc::seqptr<mix_item>{ items, items_length }; 
        // 将会走 constexpr seqptr(inc::initializer_list<item_t> const & seq); 这个重载
        // 需要使用小括号才表示两个参数，用花括号会被当成 initializer_list 
        auto list           = inc::seqptr<mix_item>(items, items_length);
        auto info           = inc::c08{message}.logger_helper(list, [&](uxx length){
            if (length < inc::static_length_of(buffer)){
                return buffer;
            }
            else{
                need_free   = true;
                return inc::memory::alloc<char>(xsizeof(char) * length);
            }
        });

        g_print_mutex.lock_non_load_store([&](){
            tty_color_t color = tty->forecolor;
            log_header_lock_free(log_type, file, line, func_name);
            log_set_color(message_type);
            tty.write_line(info);
            tty->forecolor = color;
        });

        if (need_free){
            inc::memory::free<char>(asciis(info), xsizeof(char) * info->length);
        }
    }
}
